/**
 * 工具注册和发现系统
 * 提供动态加载和管理工具包的功能
 */

import { promises as fs } from 'fs';
import { join, resolve } from 'path';
import type { ToolDefinition, ToolMeta } from './tool-schema.js';
import { logger, createErrorLogContext } from '../utils/logger.js';

// 工具包接口
export interface ToolPackage {
  tools: ToolDefinition[];
  meta: {
    /** 工具包名称，同时作为工具前缀使用 */
    name: string;
    version: string;
    description?: string;
    author?: string;
  };
}

// 工具注册表
export class ToolRegistry {
  private tools: Map<string, ToolDefinition> = new Map();
  private packages: Map<string, ToolPackage> = new Map();

  /**
   * 注册单个工具
   */
  registerTool(tool: ToolDefinition): void {
    if (this.tools.has(tool.meta.name)) {
      logger.warn('ToolRegistry: Tool already registered, overwriting', {
        toolName: tool.meta.name
      });
    }
    this.tools.set(tool.meta.name, tool);
  }

  /**
   * 注册工具包
   */
  registerPackage(packageName: string, toolPackage: ToolPackage): void {
    // 存储原始工具包
    this.packages.set(packageName, toolPackage);

    // 注册每个工具，检查命名冲突
    for (const tool of toolPackage.tools) {
      if (this.tools.has(tool.meta.name)) {
        logger.warn('ToolRegistry: Tool name conflict', {
          toolName: tool.meta.name,
          packageName,
          message: 'Tool from package conflicts with existing tool and will override it'
        });
      }
      this.registerTool(tool);
    }

    const toolNames = toolPackage.tools.map(t => t.meta.name).join(', ');
    logger.info('ToolRegistry: Registered tool package', {
      packageName,
      toolCount: toolPackage.tools.length,
      tools: toolNames
    });
  }

  /**
   * 获取工具
   */
  getTool(name: string): ToolDefinition | undefined {
    return this.tools.get(name);
  }

  /**
   * 获取所有工具
   */
  getAllTools(): ToolDefinition[] {
    return Array.from(this.tools.values());
  }

  /**
   * 获取工具元数据列表
   */
  getToolMetas(): ToolMeta[] {
    return Array.from(this.tools.values()).map(tool => tool.meta);
  }

  /**
   * 获取工具包
   */
  getPackage(name: string): ToolPackage | undefined {
    return this.packages.get(name);
  }

  /**
   * 获取所有工具包
   */
  getAllPackages(): Array<{ name: string; package: ToolPackage }> {
    return Array.from(this.packages.entries()).map(([name, pkg]) => ({ name, package: pkg }));
  }

  /**
   * 检查工具是否存在
   */
  hasTool(name: string): boolean {
    return this.tools.has(name);
  }

  /**
   * 移除工具
   */
  unregisterTool(name: string): boolean {
    return this.tools.delete(name);
  }

  /**
   * 移除工具包
   */
  unregisterPackage(packageName: string): boolean {
    const toolPackage = this.packages.get(packageName);
    if (toolPackage) {
      // 移除包中的所有工具
      for (const tool of toolPackage.tools) {
        this.tools.delete(tool.meta.name);
      }
      return this.packages.delete(packageName);
    }
    return false;
  }

  /**
   * 根据前缀获取工具列表
   * 注意：这个方法依赖于工具名称的命名约定（使用下划线分隔）
   */
  getToolsByPrefix(prefix: string): ToolDefinition[] {
    const prefixPattern = `${prefix}_`;
    return Array.from(this.tools.values()).filter(tool => tool.meta.name.startsWith(prefixPattern));
  }

  /**
   * 获取所有前缀
   */
  getAllPrefixes(): string[] {
    const prefixes = new Set<string>();
    for (const toolPackage of this.packages.values()) {
      if (toolPackage.meta?.name) {
        prefixes.add(toolPackage.meta.name);
      }
    }
    return Array.from(prefixes);
  }

  /**
   * 清空所有工具和包
   */
  clear(): void {
    this.tools.clear();
    this.packages.clear();
  }

  /**
   * 自动发现并加载指定目录下的工具包
   */
  async autoDiscoverTools(toolsDir: string): Promise<void> {
    try {
      const entries = await fs.readdir(toolsDir, { withFileTypes: true });
      
      // 使用Promise.all确保所有工具包都完全加载
      const loadPromises = entries.map(async (entry) => {
        if (entry.isDirectory()) {
          const packageDir = join(toolsDir, entry.name);
          await this.loadToolPackage(entry.name, packageDir);
        }
      });
      
      await Promise.all(loadPromises);
    } catch (error) {
      logger.error('ToolRegistry: Failed to auto-discover tools', createErrorLogContext(error, {
        toolsDir
      }));
      throw error; // 重新抛出错误，让调用者知道
    }
  }

  /**
   * 加载单个工具包
   */
  async loadToolPackage(packageName: string, packageDir: string): Promise<void> {
    try {
      const indexPath = join(packageDir, 'index.js');
      const tsIndexPath = join(packageDir, 'index.ts');

      let modulePath: string;

      // 检查是否存在index文件
      try {
        await fs.access(indexPath);
        modulePath = resolve(indexPath);
      } catch (jsError) {
        try {
          await fs.access(tsIndexPath);
          modulePath = resolve(tsIndexPath);
        } catch (tsError) {
          logger.warn('ToolRegistry: No index file found in tool package', createErrorLogContext(tsError, {
            packageName,
            packageDir,
            jsError: jsError instanceof Error ? jsError.message : String(jsError)
          }));
          return;
        }
      }

      // 动态导入工具包，增加时间戳防止缓存问题
      const module = await import(`file://${modulePath}?t=${Date.now()}`);

      // 检查导出格式
      if (typeof module.default === 'object' && 'tools' in module.default && 'meta' in module.default) {
        // 默认导出是工具包
        this.registerPackage(packageName, module.default);
      } else if (Array.isArray(module.tools) && module.meta) {
        // 命名导出tools数组
        const toolPackage: ToolPackage = {
          tools: module.tools,
          meta: module.meta,
        };
        this.registerPackage(packageName, toolPackage);
      } else {
        logger.error('ToolRegistry: Invalid package structure', {
          packageName,
          hasDefault: !!module.default,
          hasTools: !!module.tools,
          hasMeta: !!module.meta,
          defaultType: typeof module.default,
          toolsType: typeof module.tools
        });
        throw new Error(`Tool package '${packageName}' does not export a valid package structure`);
      }
    } catch (error) {
      logger.error('ToolRegistry: Failed to load tool package', createErrorLogContext(error, {
        packageName,
        packageDir
      }));
      throw error; // 重新抛出错误
    }
  }

  /**
   * 重新加载工具包
   */
  async reloadToolPackage(packageName: string, packageDir: string): Promise<void> {
    this.unregisterPackage(packageName);
    await this.loadToolPackage(packageName, packageDir);
  }

  /**
   * 获取统计信息
   */
  getStats(): {
    toolCount: number;
    packageCount: number;
    categories: Record<string, number>;
    authors: Record<string, number>;
    prefixes: string[];
    toolsByPrefix: Record<string, number>;
  } {
    const categories: Record<string, number> = {};
    const authors: Record<string, number> = {};
    const prefixes = this.getAllPrefixes();
    const toolsByPrefix: Record<string, number> = {};

    // 统计工具的分类和作者
    for (const tool of this.tools.values()) {
      if (tool.meta.category) {
        categories[tool.meta.category] = (categories[tool.meta.category] || 0) + 1;
      }
      if (tool.meta.author) {
        authors[tool.meta.author] = (authors[tool.meta.author] || 0) + 1;
      }
    }

    // 统计每个前缀的工具数量
    for (const prefix of prefixes) {
      toolsByPrefix[prefix] = this.getToolsByPrefix(prefix).length;
    }

    return {
      toolCount: this.tools.size,
      packageCount: this.packages.size,
      categories,
      authors,
      prefixes,
      toolsByPrefix,
    };
  }
}

// 全局工具注册表实例
export const globalToolRegistry = new ToolRegistry();
